package com.hc.comm.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.hc.comm.aop.fastjson.JsonpModel;
import com.hc.comm.exception.OprationStatus;
import com.hc.comm.model.ResultModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

public class JsonUtils {

    // jsonp函数名称
    public static final String[] jsonpFunctionNames = {"callback", "jsonp"};

    /**
     * contentType
     */
    public static final String mediaType = "text/json; charset=UTF-8";

    /**
     * 编码集
     */
    public final static String UTF8 = "UTF-8";

    /**
     * fastjson
     */
    public final static SerializerFeature[] features = {
            SerializerFeature.WriteNullBooleanAsFalse,
            SerializerFeature.QuoteFieldNames,
            SerializerFeature.WriteDateUseDateFormat,
            SerializerFeature.WriteNullStringAsEmpty};

    /**
     * 判断是否是一个jsonp请求
     *
     * @param request
     * @return
     * @throws Exception boolean
     * @date 2016年1月28日 上午11:45:55
     */
    public static boolean isJsonp(HttpServletRequest request) {
        for (String jsonpFunctionName : jsonpFunctionNames) {
            if (request.getParameter(jsonpFunctionName) != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取jsonp名称
     *
     * @param request
     * @return String
     * @date 2016年1月28日 下午1:09:20
     */
    public static String getJsonpFunctionName(HttpServletRequest request) {
        for (String jsonpFunctionName : jsonpFunctionNames) {
            if (request.getParameter(jsonpFunctionName) != null) {
                return request.getParameter(jsonpFunctionName);
            }
        }
        return null;
    }

    /**
     * 转jsonp
     *
     * @param resultModel
     * @return byte[]
     * @date 2016年1月28日 下午1:19:25
     */
    public static String toJsonOrJsonp(Object resultModel) {
        String jsonpFunctionName = null;
        if (resultModel instanceof JsonpModel) {
            jsonpFunctionName = ((JsonpModel) resultModel)
                    .getJsonpFunctionName();
            resultModel = ((JsonpModel) resultModel).getResult();
        }
        String text = toJSONString(resultModel);
        // String text = JSON.toJSONString(resultModel, features);
        return StringUtils.isBlank(jsonpFunctionName) ? text
                : String.format("%s(%s)", jsonpFunctionName, text);
    }

    /**
     * 输出到客户端
     *
     * @param response
     * @param message
     * @throws IOException void
     * @date 2016年1月28日 下午1:19:44
     */
    public static void outputMessage(HttpServletRequest request,
                                     HttpServletResponse response, String message) throws IOException {
        Object resultModel = toErrorResult(message);
        if (JsonUtils.isJsonp(request)) {
            resultModel = new JsonpModel(
                    JsonUtils.getJsonpFunctionName(request), resultModel);
        }
        outputMessage(response, JsonUtils.toJsonOrJsonp(resultModel));
    }


    /**
     * 输出到客户端
     *
     * @param response
     * @param message
     * @throws IOException void
     * @date 2016年1月28日 下午1:19:44
     */
    public static void outputMessage(HttpServletResponse response,
                                     String message) throws IOException {
        response.setContentType("text/json; charset=UTF-8");
        response.setCharacterEncoding(UTF8);
        response.setHeader("Cache-Control", "no-cache");
        response.getWriter().write(message);
    }

    /**
     * 对象转jsonstring
     *
     * @param object
     * @return String
     * @date 2016年2月14日 下午2:50:52
     */
    public static String toJSONString(Object object) {
        return toJSONString(object, false);
    }

    /**
     * 对象转jsonstring
     *
     * @param object
     * @param format
     * @return String
     * @date 2016年2月14日 下午2:51:10
     */
    public static String toJSONString(Object object, boolean format) {
        if (format) {
            return JSON.toJSONString(object,
                    SerializerFeature.WriteNonStringKeyAsString,
                    SerializerFeature.WriteNullStringAsEmpty,
                    SerializerFeature.DisableCircularReferenceDetect,
                    SerializerFeature.WriteMapNullValue,
                    SerializerFeature.PrettyFormat);
        } else {
            return JSON.toJSONString(object,
                    SerializerFeature.WriteNonStringKeyAsString,
                    SerializerFeature.WriteNullStringAsEmpty,
                    SerializerFeature.DisableCircularReferenceDetect,
                    SerializerFeature.WriteMapNullValue);
        }
    }


    /**
     * 是否是一个Ajax请求
     *
     * @param handler
     * @return boolean
     * @date 2015年12月13日 下午5:49:26
     */
    public static boolean isAjax(Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            ResponseBody annotation = handlerMethod
                    .getMethodAnnotation(ResponseBody.class);
            if (annotation != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 返回一个任意类型
     *
     * @param obj
     * @return
     */
    public static ResultModel toResult(Object obj) {
        return new ResultModel(HttpStatus.OK.value(),
                OprationStatus.NORMAL.getCode(), "ok", obj);
    }

    /**
     * 返回一个任意类型
     *
     * @param obj
     * @return
     */
    public static ResultModel toResult(String msg, Object obj) {
        return new ResultModel(HttpStatus.OK.value(),
                OprationStatus.NORMAL.getCode(), msg, obj);
    }

    /**
     * 重新绑定用户信息
     *
     * @param obj
     * @return
     */
    public static ResultModel toAgainResult(Object obj) {
        return new ResultModel(HttpStatus.OK.value(),
                OprationStatus.AGAIN.getCode(), "ok", obj);
    }

    /**
     * 访问正常
     *
     * @param message
     * @return
     */
    public static ResultModel toResult(String message) {
        return new ResultModel(HttpStatus.OK.value(),
                OprationStatus.NORMAL.getCode(), message);
    }

    /**
     * 禁止访问
     *
     * @param message
     * @return
     */
    private static ResultModel toErrorResult(String message) {
        return new ResultModel(HttpStatus.FORBIDDEN.value(),
                OprationStatus.ERROR.getCode(), message);
    }

    /**
     * 访问失败
     *
     * @param message
     * @return
     */
    private static ResultModel toFailResult(String message) {
        return new ResultModel(HttpStatus.OK.value(),
                OprationStatus.FAIL.getCode(), message);
    }

    /**
     * 请求失败，只返回一个错误提示
     *
     * @param request
     * @param response
     * @param message
     * @throws Exception
     */
    public static void toErrorResult(HttpServletRequest request, HttpServletResponse response, String message) throws Exception {
        Object resultModel = JsonUtils.toFailResult(message);
        if (JsonUtils.isJsonp(request)) {
            resultModel = new JsonpModel(
                    JsonUtils.getJsonpFunctionName(request), resultModel);
        }
        outputMessage(response, JsonUtils.toJsonOrJsonp(resultModel));
    }

    /**
     * 返回一个错误信息
     *
     * @param request
     * @param response
     * @param message    信息提示
     * @param optionCode 错误操作码 #OprationStatus
     * @throws Exception
     */
    public static void toErrorResult(HttpServletRequest request, HttpServletResponse response, String message, int optionCode) throws Exception {
        Object resultModel = new ResultModel(HttpStatus.OK.value(),
                optionCode, message);
        if (JsonUtils.isJsonp(request)) {
            resultModel = new JsonpModel(
                    JsonUtils.getJsonpFunctionName(request), resultModel);
        }
        outputMessage(response, JsonUtils.toJsonOrJsonp(resultModel));
    }

    /**
     * 过滤model字段
     *
     * @param message
     * @param properties
     * @return
     */
    public static String getFilterJson(Object message, String... properties) {
        SimplePropertyPreFilter filter = null;
        if (message != null && message instanceof Collection && properties != null) {
            filter = new SimplePropertyPreFilter(message.getClass().getDeclaringClass(), properties);
        } else if (message != null && properties != null) {
            filter = new SimplePropertyPreFilter(message.getClass(), properties);
        }
        SerializerFeature feature = SerializerFeature.DisableCircularReferenceDetect;
       // getResultObject(JSONObject.toJSONString(message, filter, feature), properties);
        return JSONObject.toJSONString(message, filter, feature);
    }

    public static void getResultObject(String message, String... properties) {
        JSONObject jsonObject = JSON.parseObject(message);
        final Set<String> includes = new HashSet<String>();
        for (String item : properties) {
            if (item != null) {
                includes.add(item);
            }
        }
        if (jsonObject != null) {
            Iterator it = jsonObject.keySet().iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }

    /**
     * 获取过滤后的object
     *
     * @param message
     * @param properties
     * @return
     * @throws Exception
     */
    public static Object getFilterObject(Object message, String... properties) throws Exception {
        return JSON.parse(getFilterJson(message, properties));
    }

    /**
     * 请求成功后返回字段,一个model类
     * 需要有过滤字段
     *
     * @param request
     * @param response
     * @param message
     * @param properties 过滤用的字段可以为空
     * @throws Exception
     */

    public static void toSuccessResult(HttpServletRequest request, HttpServletResponse response, Object message, String... properties) throws Exception {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        if (message != null) {
            String jsonString = getFilterJson(message, properties);
            resultMap.put(message.getClass().getSimpleName(), JSON.parse(jsonString));
        }
        toSuccessResult(request, response, resultMap);
    }

//    /**
//     * 返回多个字段的resultMap
//     *
//     * @param request
//     * @param response
//     * @param resultMap
//     * @throws Exception
//     */
//    public static void toSuccessResult(HttpServletRequest request, HttpServletResponse response, Map<String, Object> resultMap) throws Exception {
//        toSuccessResult(request, response, resultMap);
//    }

    /**
     * 正常结果返回，只返回data
     *
     * @param request
     * @param response
     * @param message
     * @throws Exception
     */
    public static void toSuccessResult(HttpServletRequest request, HttpServletResponse response, Object message)
            throws Exception {
        Object resultModel = JsonUtils.toResult(message);
        if (JsonUtils.isJsonp(request)) {
            resultModel = new JsonpModel(
                    JsonUtils.getJsonpFunctionName(request), resultModel);
        }
        outputMessage(response, JsonUtils.toJsonOrJsonp(resultModel));
    }

    /**
     * 正常结果返回，只返回message
     *
     * @param request
     * @param response
     * @param msg      提示语
     * @param obj      返回数据
     * @throws Exception
     */
    public static void toSuccessResult(HttpServletRequest request, HttpServletResponse response, String msg, Object obj)
            throws Exception {
        Object resultModel = JsonUtils.toResult(msg, obj);
        if (JsonUtils.isJsonp(request)) {
            resultModel = new JsonpModel(
                    JsonUtils.getJsonpFunctionName(request), resultModel);
        }
        outputMessage(response, JsonUtils.toJsonOrJsonp(resultModel));
    }
}
